//
//  AudioSessionManager.swift
//  CMB250716
//
//  Created by Assistant on 2024-07-28.
//

import Foundation
import AVFoundation
import UIKit

// MARK: - 音频会话管理器
class AudioSessionManager: ObservableObject {
    static let shared = AudioSessionManager()
    
    @Published var canPlayVideo = true
    private var isOtherAudioPlaying = false
    private var isAppInBackground = false
    
    private init() {
        setupNotifications()
        configureAudioSession()
    }
    
    // MARK: - 公共方法
    
    /// 配置视频播放的音频会话
    func configureForVideoPlayback() {
        guard AudioConfig.shouldEnableSmartAudioFocus() else {
            return
        }
        
        do {
            let (category, options) = AudioConfig.getCurrentAudioSessionConfig()
            try AVAudioSession.sharedInstance().setCategory(category, options: options)
            try AVAudioSession.sharedInstance().setActive(true)
            

        } catch {

        }
        
        // 开始监听音频中断
        if AudioConfig.Compatibility.enableAudioInterruptionMonitoring {
            NotificationCenter.default.addObserver(
                forName: AVAudioSession.interruptionNotification,
                object: nil,
                queue: .main
            ) { [weak self] notification in
                self?.handleAudioInterruption(notification: notification)
            }
        }
        
        // 开始监听音频路由变化
        if AudioConfig.Compatibility.enableAudioRouteChangeMonitoring {
            NotificationCenter.default.addObserver(
                forName: AVAudioSession.routeChangeNotification,
                object: nil,
                queue: .main
            ) { [weak self] notification in
                self?.handleAudioRouteChange(notification: notification)
            }
        }
    }
    
    /// 请求视频播放权限
    func requestVideoPlayback() -> Bool {
        updateAudioState()
        
        guard AudioConfig.VideoPlayback.pauseWhenOtherAudioPlaying,
              !isOtherAudioPlaying,
              !isAppInBackground else {
            canPlayVideo = false

            return false
        }
        
        canPlayVideo = true
           return true
    }
    
    // MARK: - 私有方法
    
    private func configureAudioSession() {
        do {
            let audioSession = AVAudioSession.sharedInstance()
            try audioSession.setCategory(.playback, options: [.mixWithOthers, .duckOthers])
            try audioSession.setActive(true)
        } catch {

        }
    }
    
    private func setupNotifications() {
        NotificationCenter.default.addObserver(
            forName: UIApplication.didEnterBackgroundNotification,
            object: nil,
            queue: .main
        ) { [weak self] _ in
            self?.appDidEnterBackground()
        }
        
        NotificationCenter.default.addObserver(
            forName: UIApplication.willEnterForegroundNotification,
            object: nil,
            queue: .main
        ) { [weak self] _ in
            self?.appWillEnterForeground()
        }
    }
    
    private func updateAudioState() {
        let audioSession = AVAudioSession.sharedInstance()
        isOtherAudioPlaying = audioSession.isOtherAudioPlaying
        
        // 根据配置决定是否因其他音频播放而暂停视频
        let shouldPauseForOtherAudio = AudioConfig.VideoPlayback.pauseWhenOtherAudioPlaying && isOtherAudioPlaying
        let shouldPauseForBackground = AudioConfig.VideoPlayback.pauseWhenAppInBackground && isAppInBackground
        
        let newCanPlayVideo = !shouldPauseForOtherAudio && !shouldPauseForBackground
        
        if canPlayVideo != newCanPlayVideo {
            canPlayVideo = newCanPlayVideo
            
            // 发送通知
            if canPlayVideo {
                NotificationCenter.default.post(name: .videoShouldResume, object: nil)
            } else {
                NotificationCenter.default.post(name: .videoShouldStop, object: nil)
            }
        }
    }
    
    // MARK: - 通知处理
    
    private func handleAudioInterruption(notification: Notification) {
        guard let userInfo = notification.userInfo,
              let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
              let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
            return
        }
        
        switch type {
        case .began:
            // 音频中断开始
            canPlayVideo = false
            NotificationCenter.default.post(name: .videoShouldStop, object: nil)
            
        case .ended:
            // 音频中断结束
            if let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt {
                let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
                if options.contains(.shouldResume) {
                    // 延迟恢复播放
                    DispatchQueue.main.asyncAfter(deadline: .now() + AudioConfig.VideoPlayback.interruptionRecoveryDelay) {
                        self.updateAudioState()
                    }
                }
            }
            
        @unknown default:
            break
        }
    }
    
    private func handleAudioRouteChange(notification: Notification) {
        guard let userInfo = notification.userInfo,
              let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
              let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else {
            return
        }
        
        switch reason {
        case .oldDeviceUnavailable, .newDeviceAvailable:
            // 音频设备变化，更新状态
            DispatchQueue.main.async {
                self.updateAudioState()
            }
            
        default:
            break
        }
    }
    
    private func appDidEnterBackground() {
        isAppInBackground = true
        if AudioConfig.VideoPlayback.pauseWhenAppInBackground {
            canPlayVideo = false
            NotificationCenter.default.post(name: .videoShouldStop, object: nil)
        }
    }
    
    private func appWillEnterForeground() {
        isAppInBackground = false
        
        // 检查是否可以恢复播放
        if AudioConfig.VideoPlayback.pauseWhenOtherAudioPlaying {
            updateAudioState()
        } else {
            canPlayVideo = true
            NotificationCenter.default.post(name: .videoShouldResume, object: nil)
        }
        
        // 检查其他音频播放状态
        let audioSession = AVAudioSession.sharedInstance()
        isOtherAudioPlaying = audioSession.isOtherAudioPlaying
        
        if isOtherAudioPlaying && AudioConfig.VideoPlayback.pauseWhenOtherAudioPlaying {
            canPlayVideo = false
        }
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

// MARK: - 通知扩展
extension Notification.Name {
    static let videoShouldStop = Notification.Name("videoShouldStop")
    static let videoShouldResume = Notification.Name("videoShouldResume")
}

// MARK: - 音频会话管理器扩展
extension AudioSessionManager {
    
    /// 配置指定预设的音频会话
    func configureAudioSession(for preset: AudioConfig.AudioSessionPreset) {
        guard AudioConfig.shouldEnableSmartAudioFocus() else {
            return
        }
        
        do {
            let (category, options) = AudioConfig.getAudioSessionConfig(for: preset)
            try AVAudioSession.sharedInstance().setCategory(category, options: options)
            try AVAudioSession.sharedInstance().setActive(true)
            

        } catch {

        }
    }
}